/// Rust 的面向对象特性
/*
关于一个语言被称为面向对象所需的功能，在编程社区内并未达成一致意见。Rust 被很多不同的编程范式影响，包括面向对象编程；
比如第 13 章提到了来自函数式编程的特性。面向对象编程语言所共享的一些特性往往是对象、封装和继承。让我们看一下这每一个概念的含义以及 Rust 是否支持他们。

1、对象包含数据和行为
面向对象的程序是由对象组成的。一个 对象 包含数据和操作这些数据的过程。这些过程通常被称为 方法 或 操作。
在这个定义下，Rust 是面向对象的：结构体和枚举包含数据而 impl 块提供了在结构体和枚举之上的方法。虽然带有方法的结构体和枚举并不被 称为 对象，但是他们提供了与对象相同的功能

2、封装隐藏了实现细节
另一个通常与面向对象编程相关的方面是 封装（encapsulation）的思想：对象的实现细节不能被使用对象的代码获取到。
所以唯一与对象交互的方式是通过对象提供的公有 API；使用对象的代码无法深入到对象内部并直接改变数据或者行为。
封装使得改变和重构对象的内部时无需改变使用对象的代码。
就像我们在第 7 章讨论的那样：可以使用 pub 关键字来决定模块、类型、函数和方法是公有的，而默认情况下其他一切都是私有的
*/
// 相当于 Java 中的实体类，其内的字段相当于 Java 实体类的私有成员字段
pub struct AveragedCollection {
    list: Vec<i32>,
    average: f64,
}
// 相当于 Java 中的实体类的公有方法，类似 setter 和 getter 公有方法
impl AveragedCollection {
    pub fn add(&mut self, value: i32) {
        self.list.push(value);
        self.update_average();
    }

    pub fn remove(&mut self) -> Option<i32> {
        let result = self.list.pop();
        match result {
            Some(value) => {
                self.update_average();
                Some(value)
            },
            None => None,
        }
    }

    pub fn average(&self) -> f64 {
        self.average
    }

    fn update_average(&mut self) {
        let total: i32 = self.list.iter().sum();
        self.average = total as f64 / self.list.len() as f64;
    }
}
/*
结构体自身被标记为 pub，这样其他代码就可以使用这个结构体，但是在结构体内部的字段仍然是私有的。这是非常重要的，
因为我们希望保证变量被增加到列表或者被从列表删除时，也会同时更新平均值。可以通过在结构体上实现 add、remove 和 average 方法来做到这一点，

如果封装是一个语言被认为是面向对象语言所必要的方面的话，那么 Rust 满足这个要求。在代码中不同的部分使用 pub 与否可以封装其实现细节。
*/


/// 继承，作为类型系统与代码共享
/*
继承（Inheritance）是一个很多编程语言都提供的机制，一个对象可以定义为继承另一个对象的定义，这使其可以获得父对象的数据和行为，而无需重新定义。
如果一个语言必须有继承才能被称为面向对象语言的话，那么 Rust 就不是面向对象的。无法定义一个结构体继承父结构体的成员和方法。
然而，如果你过去常常在你的编程工具箱使用继承，根据你最初考虑继承的原因，Rust 也提供了其他的解决方案。

选择继承有两个主要的原因。第一个是为了重用代码：一旦为一个类型实现了特定行为，继承可以对一个不同的类型重用这个实现。
相反 Rust 代码可以使用默认 trait 方法实现来进行共享，在示例 10-14 中我们见过在 Summary trait 上增加的 summarize 方法的默认实现。
任何实现了 Summary trait 的类型都可以使用 summarize 方法而无须进一步实现。这类似于父类有一个方法的实现，而通过继承子类也拥有这个方法的实现。
当实现 Summary trait 时也可以选择覆盖 summarize 的默认实现，这类似于子类覆盖从父类继承的方法实现。
*/
pub struct Tweet {
    pub username: String,
    pub content: String,
    reply: bool,
    retweet: bool,
}
// trait：定义共享的行为，trait 类似于其他语言中常被称为 接口（interfaces）的功能，虽然有一些不同。
pub trait Summary {
    // 抽象方法
    fn summarize_author(&self) -> String;

    // 默认方法
    fn summarize(&self) -> String {
        format!("(Read more from {}...)", self.summarize_author())
    }
}
// 相当于 Java 中的实体类并实现了一个接口
impl Summary for Tweet {
    // 构造函数
    fn new() -> Tweet {
        Tweet {
            username: String::from("horse_ebooks"),
            content: String::from("of course, as you probably already know, people"),
            reply: false,
            retweet: false,
        }
    }

    // 对于 Summary 中的抽象方法必须实现
    fn summarize_author(&self) -> String {
        format!("@{}", self.username)
    }

    // 重写了 Summary 中的同名 summarize 方法，默认私有
    fn summarize(&self) -> String {
        format!("{}: {}", self.username, self.content)
    }
}